{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Loading an Overlay\n",
    "\n",
    "By default, an overlay (bitstream) called *base* is downloaded into ",
    "the PL at boot time. The *base* overlay can be considered like ",
    "a reference design for a board.\n",
    "New overlays can be installed or copied to ",
    "the board and can be loaded into the PL as the system is running. \n",
    "\n",
    "An overlay usually includes:\n",
    "\n",
    "* A bitstream to configure the FPGA fabric\n",
    "* A Vivado design Tcl file to determine the available IP\n",
    "* Python API that exposes the IPs as attributes\n",
    "\n",
    "The PYNQ ``Overlay`` class can be used to load an overlay. An overlay is instantiated by specifying the name of the bitstream file. Instantiating the Overlay also downloads the bitstream by default and parses the Tcl file.\n",
    "\n",
    "```python\n",
    "from pynq import Overlay\n",
    "overlay = Overlay(\"base.bit\")\n",
    "```\n",
    "\n",
    "For the base overlay, we can use the existing ``BaseOverlay`` class; this class exposes the IPs available\n",
    "on the bitstream as attributes of this class."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from pynq.overlays.base import BaseOverlay\n",
    "base_overlay = BaseOverlay(\"base.bit\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once an overlay has been instantiated, the ``help()`` method can be used to discover what is in an overlay about. The *help* information can be used to interact with the overlay. Note that if you try the following code on your own board, you may see different results depending on the version of PYNQ you are using, and which board you have. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on BaseOverlay in module pynq.overlays.base.base object:\n",
      "\n",
      "class BaseOverlay(pynq.overlay.Overlay)\n",
      " |  The Base overlay for the Pynq-Z1\n",
      " |  \n",
      " |  This overlay is designed to interact with all of the on board peripherals\n",
      " |  and external interfaces of the Pynq-Z1 board. It exposes the following\n",
      " |  attributes:\n",
      " |  \n",
      " |  Attributes\n",
      " |  ----------\n",
      " |  iop_pmoda : IOP\n",
      " |       IO processor connected to the PMODA interface\n",
      " |  iop_pmodb : IOP\n",
      " |       IO processor connected to the PMODB interface\n",
      " |  iop_arduino : IOP\n",
      " |       IO processor connected to the Arduino/ChipKit interface\n",
      " |  trace_pmoda : pynq.logictools.TraceAnalyzer\n",
      " |      Trace analyzer block on PMODA interface, controlled by PS.\n",
      " |  trace_arduino : pynq.logictools.TraceAnalyzer\n",
      " |      Trace analyzer block on Arduino interface, controlled by PS. \n",
      " |  leds : AxiGPIO\n",
      " |       4-bit output GPIO for interacting with the green LEDs LD0-3\n",
      " |  buttons : AxiGPIO\n",
      " |       4-bit input GPIO for interacting with the buttons BTN0-3\n",
      " |  switches : AxiGPIO\n",
      " |       2-bit input GPIO for interacting with the switches SW0 and SW1\n",
      " |  rgbleds : [pynq.board.RGBLED]\n",
      " |       Wrapper for GPIO for LD4 and LD5 multicolour LEDs\n",
      " |  video : pynq.lib.video.HDMIWrapper\n",
      " |       HDMI input and output interfaces\n",
      " |  audio : pynq.lib.audio.Audio\n",
      " |       Headphone jack and on-board microphone\n",
      " |  \n",
      " |  Method resolution order:\n",
      " |      BaseOverlay\n",
      " |      pynq.overlay.Overlay\n",
      " |      pynq.pl.Bitstream\n",
      " |      builtins.object\n",
      " |  \n",
      " |  Methods defined here:\n",
      " |  \n",
      " |  __init__(self, bitfile, **kwargs)\n",
      " |      Return a new Overlay object.\n",
      " |      \n",
      " |      An overlay instantiates a bitstream object as a member initially.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      bitfile_name : str\n",
      " |          The bitstream name or absolute path as a string.\n",
      " |      download : boolean or None\n",
      " |          Whether the overlay should be downloaded. If None then the\n",
      " |          overlay will be downloaded if it isn't already loaded.\n",
      " |      \n",
      " |      Note\n",
      " |      ----\n",
      " |      This class requires a Vivado '.tcl' file to be next to bitstream file\n",
      " |      with same name (e.g. base.bit and base.tcl).\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from pynq.overlay.Overlay:\n",
      " |  \n",
      " |  __dir__(self)\n",
      " |      __dir__() -> list\n",
      " |      default dir() implementation\n",
      " |  \n",
      " |  __getattr__(self, key)\n",
      " |      Overload of __getattr__ to return a driver for an IP or\n",
      " |      hierarchy. Throws an `RuntimeError` if the overlay is not loaded.\n",
      " |  \n",
      " |  download(self)\n",
      " |      The method to download a bitstream onto PL.\n",
      " |      \n",
      " |      Note\n",
      " |      ----\n",
      " |      After the bitstream has been downloaded, the \"timestamp\" in PL will be\n",
      " |      updated. In addition, all the dictionaries on PL will\n",
      " |      be reset automatically.\n",
      " |      \n",
      " |      Returns\n",
      " |      -------\n",
      " |      None\n",
      " |  \n",
      " |  is_loaded(self)\n",
      " |      This method checks whether a bitstream is loaded.\n",
      " |      \n",
      " |      This method returns true if the loaded PL bitstream is same\n",
      " |      as this Overlay's member bitstream.\n",
      " |      \n",
      " |      Returns\n",
      " |      -------\n",
      " |      bool\n",
      " |          True if bitstream is loaded.\n",
      " |  \n",
      " |  load_ip_data(self, ip_name, data)\n",
      " |      This method loads the data to the addressable IP.\n",
      " |      \n",
      " |      Calls the method in the super class to load the data. This method can\n",
      " |      be used to program the IP. For example, users can use this method to\n",
      " |      load the program to the Microblaze processors on PL.\n",
      " |      \n",
      " |      Note\n",
      " |      ----\n",
      " |      The data is assumed to be in binary format (.bin). The data name will\n",
      " |      be stored as a state information in the IP dictionary.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      ip_name : str\n",
      " |          The name of the addressable IP.\n",
      " |      data : str\n",
      " |          The absolute path of the data to be loaded.\n",
      " |      \n",
      " |      Returns\n",
      " |      -------\n",
      " |      None\n",
      " |  \n",
      " |  reset(self)\n",
      " |      This function resets all the dictionaries kept in the overlay.\n",
      " |      \n",
      " |      This function should be used with caution.\n",
      " |      \n",
      " |      Returns\n",
      " |      -------\n",
      " |      None\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors inherited from pynq.pl.Bitstream:\n",
      " |  \n",
      " |  __dict__\n",
      " |      dictionary for instance variables (if defined)\n",
      " |  \n",
      " |  __weakref__\n",
      " |      list of weak references to the object (if defined)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(base_overlay)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This will give a list of the IP and methods available as part of the overlay.\n",
    "\n",
    "From the ``help()`` print out above, it can be seen that in this case the overlay includes an ``leds`` instance, and from the report this is an AxiGPIO class:\n",
    "\n",
    "```python\n",
    "    \"\"\"\n",
    "    leds : AxiGPIO\n",
    "\n",
    "         4-bit output GPIO for interacting with the green LEDs LD0-3\n",
    "    \"\"\"\n",
    "```\n",
    "\n",
    "Running ``help()`` on the leds object will provide more information about the object including details of its API. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on Channel in module pynq.lib.axigpio object:\n",
      "\n",
      "class Channel(builtins.object)\n",
      " |  Class representing a single channel of the GPIO controller.\n",
      " |  \n",
      " |  Wires are and bundles of wires can be accessed using array notation\n",
      " |  with the methods on the wires determined by the type of the channel::\n",
      " |  \n",
      " |      input_channel[0].read()\n",
      " |      output_channel[1:3].on()\n",
      " |  \n",
      " |  This class instantiated not used directly, instead accessed through\n",
      " |  the `AxiGPIO` classes attributes. This class exposes the wires\n",
      " |  connected to the channel as an array or elements. Slices of the\n",
      " |  array can be assigned simultaneously.\n",
      " |  \n",
      " |  Methods defined here:\n",
      " |  \n",
      " |  __getitem__(self, idx)\n",
      " |  \n",
      " |  __init__(self, parent, channel)\n",
      " |      Initialize self.  See help(type(self)) for accurate signature.\n",
      " |  \n",
      " |  __len__(self)\n",
      " |  \n",
      " |  read(self)\n",
      " |      Read the state of the input pins\n",
      " |  \n",
      " |  setdirection(self, direction)\n",
      " |      Set the direction of the channel\n",
      " |      \n",
      " |      Must be one of AxiGPIO.{Input, Output, InOut} or the string\n",
      " |      'in', 'out', or 'inout'\n",
      " |  \n",
      " |  setlength(self, length)\n",
      " |      Set the number of wires connected to the channel\n",
      " |  \n",
      " |  wait_for_interrupt_async(self)\n",
      " |      Wait for the interrupt on the channel to be signalled\n",
      " |      \n",
      " |      This is intended to be used by slices waiting for a particular\n",
      " |      value but can be used in any situation to wait for a per-channel\n",
      " |      interrupt.\n",
      " |  \n",
      " |  write(self, val, mask)\n",
      " |      Set the state of the output pins\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors defined here:\n",
      " |  \n",
      " |  __dict__\n",
      " |      dictionary for instance variables (if defined)\n",
      " |  \n",
      " |  __weakref__\n",
      " |      list of weak references to the object (if defined)\n",
      " |  \n",
      " |  trimask\n",
      " |      Gets or sets the tri-state mask for an inout channel\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(base_overlay.leds)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The API can be used to control the object. For example, the following cell will turn on LD0 on the board."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "base_overlay.leds[0].toggle()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Information about other IP can be found from the overlay instance in a similar way, as shown below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on HDMIWrapper in module pynq.lib.video object:\n",
      "\n",
      "class HDMIWrapper(pynq.overlay.DefaultHierarchy)\n",
      " |  Hierarchy driver for the entire Pynq-Z1 video subsystem.\n",
      " |  \n",
      " |  Exposes the input, output and video DMA as attributes. For most\n",
      " |  use cases the wrappers for the input and output pipelines are\n",
      " |  sufficient and the VDMA will not need to be used directly.\n",
      " |  \n",
      " |  Attributes\n",
      " |  ----------\n",
      " |  hdmi_in : pynq.lib.video.HDMIIn\n",
      " |      The HDMI input pipeline\n",
      " |  hdmi_out : pynq.lib.video.HDMIOut\n",
      " |      The HDMI output pipeline\n",
      " |  axi_vdma : pynq.lib.video.AxiVDMA\n",
      " |      The video DMA.\n",
      " |  \n",
      " |  Method resolution order:\n",
      " |      HDMIWrapper\n",
      " |      pynq.overlay.DefaultHierarchy\n",
      " |      pynq.overlay._IPMap\n",
      " |      builtins.object\n",
      " |  \n",
      " |  Methods defined here:\n",
      " |  \n",
      " |  __init__(self, description)\n",
      " |      Create a new _IPMap based on a hierarchical description.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Static methods defined here:\n",
      " |  \n",
      " |  checkhierarchy(description)\n",
      " |      Function to check if the driver matches a particular hierarchy\n",
      " |      \n",
      " |      This function should be redefined in derived classes to return True\n",
      " |      if the description matches what is expected by the driver. The default\n",
      " |      implementation always returns False so that drivers that forget don't\n",
      " |      get loaded for hierarchies they don't expect.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from pynq.overlay._IPMap:\n",
      " |  \n",
      " |  __dir__(self)\n",
      " |      __dir__() -> list\n",
      " |      default dir() implementation\n",
      " |  \n",
      " |  __getattr__(self, key)\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors inherited from pynq.overlay._IPMap:\n",
      " |  \n",
      " |  __dict__\n",
      " |      dictionary for instance variables (if defined)\n",
      " |  \n",
      " |  __weakref__\n",
      " |      list of weak references to the object (if defined)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(base_overlay.video)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
